package com.spdzen.support;

import java.util.UUID;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

public class AESUtils {
	public static final String KEY_ALGORITHM = "AES";
	public static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding";
	public static final String CHARSET = "UTF-8";
	
	/**
	 * 使用随机uuid作为key和iv，uuid的前16是key，后16位是iv。AES加密后的结果转成16进制字符串，把uuid附加在加密后的字符串前面。编码格式为UTF-8。
	 * @param content 明文
	 * @return (uuid + 加密后的16进制密文)的Base64编码
	 * @throws Exception
	 */
	public static String encrypt(String content) throws Exception {
		String uuid = UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
		String key = uuid.substring(0, 16);
		String iv = uuid.substring(16);
		
		StringBuilder sb = new StringBuilder();
		sb.append(uuid);
		
		char[] chars = Hex.encodeHex(encrypt(content.getBytes(CHARSET), key.getBytes(CHARSET), iv.getBytes(CHARSET)), true);
		sb.append(chars);
		
		return Base64.encodeBase64String(sb.toString().getBytes(CHARSET));
	}
	
	/**
	 * (uuid + AES加密后的16进制密文)的Base64编码进行解密
	 * @param word 密文
	 * @return 明文
	 * @throws Exception
	 */
	public static String decrypt(String word) throws Exception {
		String text = new String(Base64.decodeBase64(word.getBytes(CHARSET)), CHARSET);
		String key = text.substring(0, 16);
		String iv = text.substring(16, 32);
		String content = text.substring(32);
		
		return decryptToString(Hex.decodeHex(content.toCharArray()), key.getBytes(CHARSET), iv.getBytes(CHARSET));
	}
	
	public static String encryptToHex(String content, String key, String iv) throws Exception {
		return Hex.encodeHexString(encrypt(content.getBytes(CHARSET), key.getBytes(CHARSET), iv.getBytes(CHARSET)));
	}
	
	public static String encryptToBase64(String content, String key, String iv) throws Exception {
		return Base64.encodeBase64String(encrypt(content.getBytes(CHARSET), key.getBytes(CHARSET), iv.getBytes(CHARSET)));
	}
	
	public static String encryptToHex(byte[] content, byte[] key, byte[] iv) throws Exception {
		return Hex.encodeHexString(encrypt(content, key, iv));
	}
	
	public static String encryptToBase64(byte[] content, byte[] key, byte[] iv) throws Exception {
		return Base64.encodeBase64String(encrypt(content, key, iv));
	}
	
	public static byte[] encrypt(String content, String key, String iv) throws Exception {
		return encrypt(content.getBytes(CHARSET), key.getBytes(CHARSET), iv.getBytes(CHARSET));
	}
	
	public static byte[] encrypt(byte[] content, byte[] key, byte[] iv) throws Exception {
		SecretKeySpec aesKey = new SecretKeySpec(key, KEY_ALGORITHM);
        IvParameterSpec ivps = new IvParameterSpec(iv);//使用CBC模式，需要一个向量iv，可增加加密算法的强度
        
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);// 创建密码器
        cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivps);// 初始化为加密模式的密码器
        
        return cipher.doFinal(content);
	}
	
	public static byte[] decrypt(byte[] content, byte[] key, byte[] iv) throws Exception {
		SecretKeySpec aesKey = new SecretKeySpec(key, KEY_ALGORITHM);
        IvParameterSpec ivps = new IvParameterSpec(iv);//使用CBC模式，需要一个向量iv，可增加加密算法的强度
        
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);// 创建密码器
        cipher.init(Cipher.DECRYPT_MODE, aesKey, ivps);// 初始化为解密模式的密码器
        
        return cipher.doFinal(content);
	}
	
	public static String decryptToString(byte[] content, byte[] key, byte[] iv) throws Exception {
        return new String(decrypt(content, key, iv), CHARSET);
	}
	
	public static String decryptToString(String content, String key, String iv) throws Exception {
		return new String(decrypt(content.getBytes(CHARSET), key.getBytes(CHARSET), iv.getBytes(CHARSET)), CHARSET);
	}
	
	public static byte[] decrypt(String content, String key, String iv) throws Exception {
		return decrypt(content.getBytes(CHARSET), key.getBytes(CHARSET), iv.getBytes(CHARSET));
	}
}
